<template>
  <div class="continua">
    <div class="content">
      <p>---> 监听ref ---></p>
      <el-button @click="onChangeCountClick">监听count --> {{ count }}</el-button>
      <el-button @click="stopCountWatch">停止监听count --> {{ count }}</el-button>
      <hr>
      <p>---> 监听代理数据 对象 info ---></p>
      <el-button @click="onChangeInfoClick">监听info --> {{ info }}</el-button>
      <el-button @click="stopInfoWatch">停止监听 info --> {{ count }}</el-button>
      <hr>
      <p>---> 监听函数---></p>
      <el-button @click="changeFunData">监听info --> {{ funData }}</el-button>

      <p>---> 监听代理中的某一个---></p>
      <el-button @click="changeWatchData">监听info --> {{ watchData }}</el-button>
    </div>
  </div>
</template>

<script setup>
// watch:可以针听一个或多个数据，如果侦听的数据发生变化，会执行指定的函数。
import {onMounted, reactive, ref, watch} from "vue";

const count = ref(1);
const onChangeCountClick = () => {
  count.value += 1
}
// 第一个参数是侦听的数据。第二个参数是回调函数。第三个参数是一个配置对象。
// 当侦听的数据发生改变，那么会执行回调函数。
// 立即调用，如果立即调用那么 oldVal 的值是undefined
// watch的返回值是一个函数，通过调用该函数可以停止侦听(当数据发生改变，那么不会再次执行回调函数)。
const stopCountWatch = watch(count, (newVal, oldVal) => {
      console.log("原来的数据", oldVal)
      console.log("最新的数据", newVal)
    },
    {
      // immediate: true, // 立即调用
      deep: true, // 是否深度侦听，如果为true那么会监听对象中的所有属性，如果为false那么只会监听对象中的第一层属性
    }
)

// 2- 侦听数据代理对象
const info = reactive({
  userName: "zhangsan",
  age: 12,
  arr: {
    objArr: [1, 2, 3, 4]
  }
})
const onChangeInfoClick = () => {
  // 修改对象中的基本数据类型
  // info.age += 1
  // 修改对象中的引用数据类型
  info.arr.objArr.push(5)
}
const stopInfoWatch = watch(info, (newVal, oldVal) => {
  console.log("原来的数据", oldVal === newVal) // true
}, {
  // deep: true
})

// 3- 侦听一个函数，该函数返回一个数据
const funData = reactive({
  num: 12
})
const changeFunData = () => {
  funData.num += 1
}
// 函数要有一个返回值，返回值可以依赖一个或多个数据，当返回值发生改变以后会被侦听到。
const stopWatch = watch(() => count.value + funData.num, (newValue, oldValue) => {
  console.log("侦听一个函数", newValue, oldValue)
}, {
  // immediate: true
})

// 4- 侦听数组，数组内可以是所有的响应式数据
const stopArrWatch = watch([info, count], (newValue, oldValue) => {
  // newValue:[info更改后的值，count更改后的值]
  // oldValue:[info更改前的值，count更改前的值]
  console.log("侦听数组", newValue, oldValue)
}, {
  // immediate: true
})


// 主要应用于侦听代理对象中的某个属性的变化
// 如果返回的是一个引用类型，引用类型的地址没有发生改变不会被侦听，如果被侦听需要增加deep:true
const watchData = reactive({
  num: 12,
  arr: [1, 2, 3, 4, 5,]
})
const changeWatchData = () => {
  // 监听基本数据类型
  // watchData.num += 1
  // 监听引用数据类型
  watchData.arr.push(5)
}
// 监听基本数据类型
// const stopWatchData = watch(() => watchData.num, (newValue, oldValue) => {
//   console.log("代理对象中的某个属性的变化", newValue, oldValue)
// }, {
//   // deep:true,
//   // immediate: true
// })

// 监听引用数据类型
const stopWatchData = watch(() => watchData.arr, (newValue, oldValue) => {
  console.log("代理对象中的某个属性的变化", newValue, oldValue)
}, {
  // deep:true,
  // immediate: true
})
</script>

<style scoped lang="less">
.continua {
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;

  .content {
    width: 500px;
    height: 500px;
    border: 1px solid #ccc;
  }
}
</style>
